#include<bits/stdc++.h>
using namespace std;
const int MOD = 1e9+7;
const int N = 1e5+10;
int a[N];
const int P = N*100;
struct WBLT{
    int pcnt;
    int son[P][2];
    int sum[P];
    int atag[P];
    bool rtag[P];
    int rub[P],rubp;
    long long siz[P];
    bool useful[P];
    bool deleted[P];
    int gen(){
        int now;
        if(rubp){
            now = rub[rubp--];
            deleted[now] = 0;
        }else{
            now = ++pcnt;
        }
        atag[now] = rtag[now] = siz[now] = son[now][0] = son[now][1] = sum[now] = 0;
        return now;
    }
    int gen(int x){
        int now = gen();
        sum[now] = x;
        siz[now] = 1;
        return now;
    }
    void push_up(int now){
        sum[now] = (sum[son[now][0]] + sum[son[now][1]])%MOD;
        siz[now] = siz[son[now][0]] + siz[son[now][1]];
    }
    void add(int now,int v){
        sum[now] = (sum[now] + siz[now]%MOD*v%MOD)%MOD;
        atag[now] = (atag[now] + v)%MOD;
    }
    void rev(int now){
        swap(son[now][0],son[now][1]);
        rtag[now]^=1;
    }
    void copy(int &now){
        int cop = now;
        now = gen();
        son[now][0] = son[cop][0];
        son[now][1] = son[cop][1];
        siz[now] = siz[cop];
        sum[now] = sum[cop];
        atag[now] = atag[cop];
        rtag[now] = rtag[cop];
    }
    void push_down(int now){
        if(!son[now][0]){
            return;
        }
        if(!atag[now] && !rtag[now]){
            return;
        }
        copy(son[now][0]);
        copy(son[now][1]);
        if(atag[now]){
            add(son[now][0],atag[now]);
            add(son[now][1],atag[now]);
            atag[now] = 0;
        }
        if(rtag[now]){
            rev(son[now][0]);
            rev(son[now][1]);
            rtag[now] = 0;
        }
    }
    int gen(int x,int y){
        int now = gen();
        son[now][0] = x;
        son[now][1] = y;   
        push_up(now);
        return now;
    }
    int merges(int x,int y){
        if(!x || !y){
            return x +y;
        }
        long long lmt = (siz[x] + siz[y])*0.295;
        if(min(siz[x],siz[y]) >= lmt){
            return gen(x,y);
        }
        if(siz[x] > siz[y]){
            push_down(x);
            int a = son[x][0],b = son[x][1];
            if(siz[a] >= lmt){
                return merges(a,merges(b,y));
            }else{
                push_down(b);
                int m = son[b][0],n = son[b][1];
                return merges(merges(a,m),merges(n,y));
            }
        }else{
            push_down(y);
            int a = son[y][0],b = son[y][1];
            if(siz[b] >= lmt){
                return merges(merges(x,a),b);
            }else{
                push_down(a);
                int m = son[a][0],n = son[a][1];
                return merges(merges(x,m),merges(n,b));
            }
        }
    }
    void split(int now,long long rnk,int &x,int &y){
        if(!rnk){
            x = 0;
            y = now;
            return;
        }
        if(!son[now][0]){
            x = now;
            y = 0;
            return;
        }
        push_down(now);
        if(siz[son[now][0]] >= rnk){
            split(son[now][0],rnk,x,y);
            y = merges(y,son[now][1]);
        }else{
            split(son[now][1],rnk - siz[son[now][0]],x,y);
            x = merges(son[now][0],x);
        }
    }
    void splits(int now,long long rnk,int &x,int &y,bool ix,bool iy){
        if(!rnk){
            if(ix){
                x = 0;
            }
            if(iy){
                y = now;
            }
            return;
        }
        if(!son[now][0]){
            if(ix){
                x = now;
            }
            if(iy){
                y = 0;
            }
            return;
        }
        push_down(now);
        if(siz[son[now][0]] >= rnk){
            splits(son[now][0],rnk,x,y,ix,iy);
            if(iy){
                y = merges(y,son[now][1]);
            }
        }else{
            splits(son[now][1],rnk - siz[son[now][0]],x,y,ix,iy);
            if(ix){
                x = merges(son[now][0],x);
            }
        }
    }
    int build(int l,int r){
        if(l == r){
            int now = gen(a[l]);
            return now;
        }
        int mid = (l + r)/2;
        return gen(build(l,mid),build(mid+1,r));
    }
    void mark(int now){
        if(useful[now])return;
        useful[now] = 1;
        if(!son[now][0]){
            return;
        }
        mark(son[now][1]);
        mark(son[now][0]);
    }
    void unmark(int now){
        if(!useful[now])return;
        useful[now] = 0;
        if(!son[now][0]){
            return;
        }
        unmark(son[now][0]);
        unmark(son[now][1]);
    }
}wb;

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int n,m;
    cin>>n>>m;
    for(int i = 1;i<=n;i++){
        cin>>a[i];
        a[i] = (a[i] + MOD)%MOD;
    }
    int rot = wb.build(1,n);
    for(int i = 1;i<=m;i++){
        int op;
        long long l,r;
        cin>>op>>l>>r;
        if(op == 1){
            int x;
            cin>>x;
            x = (x + MOD)%MOD;
            int a,b,c;
            wb.split(rot,r,b,c);
            wb.split(b,l - 1,a,b);
            wb.copy(b);
            wb.add(b,x);
            rot = wb.merges(wb.merges(a,b),c);
        }else if(op == 2){
            int a,b,c;
            wb.split(rot,r,b,c);
            wb.split(b,l - 1,a,b);
            wb.copy(b);
            wb.rev(b);
            rot = wb.merges(wb.merges(a,b),c);    
        }else if(op == 3){
            long long p;
            cin>>p;
            int a,b,c;
            wb.splits(rot,r,b,c,1,0);
            wb.splits(b,l - 1,a,b,0,1);
            int d,e;
            wb.split(rot,p,d,e);
            rot = wb.merges(wb.merges(d,b),e);
        }else if(op == 4){
            int a,b,c;
            wb.split(rot,r,b,c);
            wb.splits(b,l - 1,a,b,1,0);
            rot = wb.merges(a,c);
        }else if(op == 5){
            int a,b,c;
            wb.splits(rot,r,b,c,1,0);
            wb.splits(b,l - 1,a,b,0,1);            
            cout<<wb.sum[b]<<'\n';
        }
        if(wb.rubp + P - wb.pcnt <= 100000){
            wb.mark(rot);
            for(int i = 1;i<=wb.pcnt;i++){
                if(!wb.deleted[i] && !wb.useful[i]){
                    wb.rub[++wb.rubp] = i;
                    wb.deleted[i] = 1;
                }
            }
            wb.unmark(rot);
        }
        cerr<<op<<'\n';
    }
}